/*
	Package fen implements parsing and printing of chess positions in
	Forsyth-Edwards Notation.

	This packages is based on the specification by Steven Edwards as part
	of the Portable Game Notation (PGN), see
	http://www.saremba.de/chessgml/standards/pgn/pgn-complete.htm#c16.1

	The chess programming wiki has a (much shorter) translation into Backus–Naur Form:
	http://chessprogramming.wikispaces.com/Forsyth-Edwards+Notation
*/
package fen

import (
	b "code.google.com/p/gochess/board"
	"code.google.com/p/gochess/notation/san"
	pos "code.google.com/p/gochess/position"
	"fmt"
)

var InitialPosition = `rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1`

var piece2Notation = map[pos.Piece]string{
	pos.WhiteKing:   "K",
	pos.WhiteQueen:  "Q",
	pos.WhiteRook:   "R",
	pos.WhiteBishop: "B",
	pos.WhiteKnight: "N",
	pos.WhitePawn:   "P",
	pos.BlackKing:   "k",
	pos.BlackQueen:  "q",
	pos.BlackRook:   "r",
	pos.BlackBishop: "b",
	pos.BlackKnight: "n",
	pos.BlackPawn:   "p",
}

func sprintPiece(piece pos.Piece) string {
	return piece2Notation[piece]
}

var color2Notation = map[pos.Color]string{
	pos.White: "w",
	pos.Black: "b",
}

func sprintColor(color pos.Color) string {
	return color2Notation[color]
}

func Sprint(p *pos.Position) string {

	// print piece placement
	output := ""
	for rank := b.Rank8; rank >= b.Rank1; rank-- {
		if rank < b.Rank8 {
			output += "/"
		}
		emptySquares := 0
		for file := b.A; file <= b.H; file++ {
			piece := p.Get(b.GetSquare(file, rank))
			if piece == pos.NoPiece {
				emptySquares++
			} else {
				if emptySquares > 0 {
					output += fmt.Sprintf("%d", emptySquares)
					emptySquares = 0
				}
				output += sprintPiece(piece)

			}
		}
		if emptySquares > 0 {
			output += fmt.Sprintf("%d", emptySquares)
		}
	}

	// print side to move
	output += fmt.Sprintf(" %s", sprintColor(p.SideToMove()))

	// print castling state
	var s string
	if p.CastlingRights().Possible(pos.White, pos.CastlingShort) {
		s += "K"
	}
	if p.CastlingRights().Possible(pos.White, pos.CastlingLong) {
		s += "Q"
	}
	if p.CastlingRights().Possible(pos.Black, pos.CastlingShort) {
		s += "k"
	}
	if p.CastlingRights().Possible(pos.Black, pos.CastlingLong) {
		s += "q"
	}
	if len(s) == 0 {
		s = "-"
	}
	output += fmt.Sprintf(" %s", s)

	// print en passant square
	s = "-"
	square := p.EnPassantTarget()
	if square != b.NoSquare {
		s = san.SprintSquare(square)
	}
	output += fmt.Sprintf(" %s", s)

	// print halfmove clock
	output += fmt.Sprintf(" %d", p.HalfmoveClock())

	// print fullmove number
	// BUG: implement this
	return output + fmt.Sprintf(" %d", 1)
}
